package com.legal.service.chat.impl;

import com.legal.service.chat.FileService;
import com.legal.utils.Tess4jUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.sourceforge.tess4j.TesseractException;
import org.springframework.ai.document.Document;
import org.springframework.ai.document.DocumentReader;
import org.springframework.ai.reader.ExtractedTextFormatter;
import org.springframework.ai.reader.pdf.PagePdfDocumentReader;
import org.springframework.ai.reader.pdf.config.PdfDocumentReaderConfig;
import org.springframework.ai.reader.tika.TikaDocumentReader;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.List;
import java.util.Objects;
import java.util.Properties;

@Slf4j
@Component
@RequiredArgsConstructor
public class FileServiceImpl implements FileService {
    // 用于存储和检索向量的向量存储实现
    private final Tess4jUtil tess4jUtil;

    // 会话id 与 文件名的对应关系，方便查询会话历史时重新加载文件(存储结构类似于HashMap)
    private final Properties chatFiles = new Properties();

    /**
     * 保存PDF文件到本地磁盘，并在内存中保存会话ID与文件名的映射关系
     *
     * @param chatId   会话ID，用于后续检索文件
     * @param resource 要保存的PDF文件资源
     * @return 文件是否保存成功
     */
    @Override
    public boolean save(String chatId, Resource resource) {

        // 2.保存到本地磁盘
        String filename = resource.getFilename();
        File target = new File(Objects.requireNonNull(filename));
        if (!target.exists()) {
            try {
                Files.copy(resource.getInputStream(), target.toPath());
            } catch (IOException e) {
                log.error("Failed to save PDF resource.", e);
                return false;
            }
        }
        // 3.保存映射关系到chat-pdf.properties中
        chatFiles.put(chatId, filename);
        return true;
    }

    /**
     * 根据会话ID获取对应的PDF文件资源
     *
     * @param chatId 会话ID
     * @return 对应的PDF文件资源，如果不存在则返回null
     */
    @Override
    public Resource getFile(String chatId) {
        return new FileSystemResource(chatFiles.getProperty(chatId));
    }

    @Override
    public String ParseFile(MultipartFile file) {
        // 1. 验证文件非空
        if (file == null || file.isEmpty()) {
            return null;
        }
        // 2. 检查文件类型
        // 图片类型
        if (file.getContentType().startsWith("image")) {
            // 2.1. 验证图片格式
            BufferedImage image;
            try {
                image = ImageIO.read(file.getInputStream());
                if (image == null) {
                    throw new IllegalArgumentException("无法解析图片文件，可能格式不支持");
                }
                // 2.2. 执行OCR识别
                return tess4jUtil.doOCR(image);
            } catch (IOException | TesseractException e) {
                throw new RuntimeException("读取文件失败", e);
            }

        }else if(file.getContentType().equals("application/pdf")){
            List<Document> documents = readPdf(file);
            StringBuilder stringBuilder = new StringBuilder();
            documents.stream().forEach(document -> {
                stringBuilder.append(document.getText());
            });
            return stringBuilder.toString();
        }
        else {
            List<Document> documents = readWithTika(file);
            StringBuilder stringBuilder = new StringBuilder();
            documents.stream().forEach(document -> {
                stringBuilder.append(document.getText());
            });
            return stringBuilder.toString();
        }


    }

    /**
     * 其他类型的文本文件，如docx，txt，xlsx，makdedown这种文本文件，使用Tika进行解析
     * @param multipartFile
     * @return
     */
    public List<Document> readWithTika(MultipartFile multipartFile) {
        try {
            // 使用InputStreamResource而不是FileSystemResource
            DocumentReader reader = new TikaDocumentReader(new InputStreamResource(multipartFile.getInputStream()));
            return reader.get();
        } catch (Exception e) {
            log.error("Failed to read MultipartFile", e);
            throw new RuntimeException("Failed to read MultipartFile", e);
        }
    }

    public List<Document> readPdf(MultipartFile multipartFile){
        // 1. 将MultipartFile转换为Resource
        Resource resource = multipartFile.getResource();

        // 2. 创建PDF读取器
        PagePdfDocumentReader reader = new PagePdfDocumentReader(
                resource,
                PdfDocumentReaderConfig.builder()
                        .withPageExtractedTextFormatter(ExtractedTextFormatter.defaults())
                        .withPagesPerDocument(1) // 每1页PDF作为一个Document
                        .build()
        );

        // 3. 读取PDF文档
        List<Document> documents = reader.read();
        return documents;
    }

}
